from unittest import TestCase

from comp_arch.amat import get_amat, get_miss_penalty, get_miss_rate


class TestAmat(TestCase):
    def test_get_amat(self):
        hit_time = 1
        miss_rate = 1
        miss_penalty = 1
        expected_amat = 2
        result = get_amat(hit_time, miss_rate, miss_penalty)
        self.assertEqual(round(result, 2), expected_amat)

    def test_get_miss_penalty(self):
        hit_time = 1
        miss_rate = 1
        miss_penalty = 1
        expected_miss_penalty = 2
        result = get_miss_penalty(hit_time, miss_rate, miss_penalty)
        self.assertEqual(round(result, 2), expected_miss_penalty)

    def test_get_miss_rate_perfect_machine(self):
        misses_L1 = 0
        misses_L2 = 0
        expected_miss_rate = 0
        result = get_miss_rate(misses_L1, misses_L2)
        self.assertEqual(round(result, 2), expected_miss_rate)

    def test_get_miss_rate_w7aBa(self):
        misses_L1 = 1000
        misses_L2 = 40
        expected_miss_rate = 0.04
        result = get_miss_rate(misses_L1, misses_L2)
        self.assertEqual(round(result, 2), expected_miss_rate)

    def test_get_miss_rate_w7aBb(self):
        misses_L1 = 40
        misses_L2 = 20
        expected_miss_rate = 0.5
        result = get_miss_rate(misses_L1, misses_L2)
        self.assertEqual(round(result, 2), expected_miss_rate)

    def test_get_miss_rate(self):
        misses_L1 = 1
        misses_L2 = 1
        expected_miss_rate = 1
        result = get_miss_rate(misses_L1, misses_L2)
        self.assertEqual(round(result, 2), expected_miss_rate)

    def test_get_amat_w7A2(self):
        memory_accesses = 1000
        misses_L1 = 50
        miss_rate_L1 = misses_L1 / memory_accesses
        misses_L2 = 20
        miss_rate_L2 = misses_L2 / miss_rate_L1
        misses_L3 = 10
        miss_rate_L3 = misses_L3 / miss_rate_L2
        miss_penalty_L3 = 100
        amat_L3 = get_amat(
            hit_time=20, miss_rate=miss_rate_L3, miss_penalty=miss_penalty_L3
        )
        amat_L2 = get_amat(hit_time=10, miss_rate=miss_rate_L2, miss_penalty=amat_L3)
        amat_L1 = get_amat(hit_time=1, miss_rate=miss_rate_L1, miss_penalty=amat_L2)
        expected_amat_L2 = 9010
        expected_miss_rate = 0.05
        expected_amat = 451.5
        self.assertEqual(round(amat_L2, 2), expected_amat_L2)
        self.assertEqual(round(miss_rate_L1, 2), expected_miss_rate)
        self.assertEqual(round(amat_L1, 2), expected_amat)
